﻿using System;
using System.Threading;
using Com.Fubei.OpenApi.Sdk;
using Com.Fubei.OpenApi.Sdk.Extensions;
using Com.Fubei.OpenApi.Sdk.Utils;
using FubeiOpenApiDemo.Api.Request;
using FubeiOpenApiDemo.Api.Response;

// 备注：
// 在InitConfig() 方法中填入AppId/AppSecret或者VendorSn或者VendorSecret
// 服务商后端对接推荐使用 VendorSn、VendorSecret；参数中必须带MerchantId
// 客户端集成对接推荐使用 AppId、AppSecret
// PostApiRequest 最后一个参数可以指定是服务商级调用还是商户级调用
namespace FubeiOpenApiDemo
{
    internal static class Program
    {
        // todo 服务商维度调用必须指定MerchantId和StoreId
        private const int MerchantId = 0;

        // todo 商户维护调用，超过1个门店时，必须设置StoreId
        private const int StoreId = 0;
        
        public static void Main(string[] args)
        {
            InitConfig();
            // 付款
            OrderPay();
            // 退款
            Refund();
        }

        /// <summary>
        /// 1. 初始化配置，填入AppId和AppSecret
        /// 备注：服务商级调用请填入VendorSn和VendorSecret
        /// </summary>
        private static void InitConfig()
        {
            var cfg = FubeiOpenApiGlobalConfig.Instance;
            // 商户级API，所有操作仅限于商户范围，建议客户端对接使用
            cfg.AppId = "";
            cfg.AppSecret = "";
            
            // 服务商级API 权限较大，建议后端对接使用
            cfg.VendorSn = "";
            cfg.VendorSecret = "";
        }

        /// <summary>
        /// 生成订单号
        /// </summary>
        /// <param name="prefix"></param>
        /// <returns></returns>
        private static string GenerateOrderSn(string prefix = "")
        {
            // 请按照规则自定生成
            var bizNo = string.Format("{0:yyyyMMddHHmmssfff}{1}", DateTime.Now, RandomStringUtil.RandomNumeric(5));
            return string.Format("{0}{1}", prefix, bizNo);
        }

        /// <summary>
        /// 订单支付
        /// </summary>
        private static void OrderPay()
        {
            // todo 金额
            var amount = 0.1m;
            // todo 付款码
            var barcode = "";

            var param = new AOrderPayParam
            {
                // todo 请按照业务规则生成订单号，这里随便用时间生成了
                MerchantOrderSn = GenerateOrderSn("DEMO_ORDER"),
                StoreId = StoreId,
                // MerchantId 这个字段，如果是商户级别调用，则可不传
                // MerchantId = MerchantId,
                TotalAmount = amount,
                AuthCode = barcode
            };
            try
            {
                var response = 
                    FubeiOpenApiSdk.PostApiRequest<AOrderPayResultEntity>("fbpay.order.pay", param);
                
                Console.WriteLine("付款码支付结果: {0}", response.SerializeAsJson());
                // 订单状态：USERPAYING需要继续查询订单状态
                var tradeState = response.OrderStatus;
                // 重试次数，请根据实际情况进行
                var retryCount = 30;
                // 当订单状态是USERPAYING
                while (Equals("USERPAYING", tradeState) && retryCount > 0)
                {
                    --retryCount;
                    var queryResponse =  FubeiOpenApiSdk.PostApiRequest<AOrderQueryResultEntity>("fbpay.order.query", new AOrderQueryParam
                    {
                        // MerchantId这个字段，如果是商户级别调用，则可不传
                        // MerchantId = MerchantId,
                        MerchantOrderSn = response.MerchantOrderSn
                    });
                    tradeState = queryResponse.OrderStatus;
                    Console.WriteLine(string.Format("付款码支付结果: {0}", queryResponse.SerializeAsJson()));
                    // 等待1秒钟后重新查询
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("请求失败: {0}", ex);
            }
        }
        
        /// <summary>
        /// 退款
        /// </summary>
        private static void Refund()
        {
            // 需要退款的订单号
            // todo: 填入 order_sn，refund_sn，merchant_order_sn 三选一
            var merchantOrderSn = "";
            var merchantRefundSn = GenerateOrderSn("DEMO_RF");
            var refundAmount = 0.1m;
            
            var param = new ARefundOrderParam
            {
                MerchantOrderSn = merchantOrderSn,
                MerchantRefundSn = merchantRefundSn,
                // MerchantId 这个字段，如果是商户级别调用，则可不传
                // MerchantId = MerchantId,
                RefundAmount = refundAmount
            };
            try
            {
                var response = 
                    FubeiOpenApiSdk.PostApiRequest<ARefundOrderResultEntity>("fbpay.order.refund", param);
                
                Console.WriteLine("退款申请结果: {0}", response.SerializeAsJson());
                // 退款状态：REFUND_PROCESSING需要继续查询退款状态
                var tradeState = response.RefundStatus;
                // 重试次数，请根据实际情况进行
                var retryCount = 30;
                // 当订单状态是REFUND_PROCESSING
                while (Equals("REFUND_PROCESSING", tradeState) && retryCount > 0)
                {
                    --retryCount;
                    var queryResponse = FubeiOpenApiSdk.PostApiRequest<ARefundOrderResultEntity>("fbpay.order.refund.query", new AQueryRefundParam
                    {
                        // 这个字段，如果是商户级别调用，则可不传
                        // MerchantId = AMerchantId,
                        MerchantRefundSn = response.MerchantRefundSn
                    });
                    tradeState = queryResponse.RefundStatus;
                    Console.WriteLine("退款查询结果: {0}", queryResponse.SerializeAsJson());
                    // 等待1秒钟后重新查询
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("请求失败: {0}", ex);
            }
        }
    }
}